package de.lighti.starcraft.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Logger;

import de.lighti.starcraft.model.StarcraftBot;
import de.lighti.starcraft.model.StarcraftMap;

public class IniParser {
    private final static Logger LOGGER = Logger.getLogger( IniParser.class.getName() );

    private final static String BOT_SECTION = "bots";
    private final static String BOT_SECTION_BENCHMARK = "bots-bench";

    public static Vector<StarcraftBot> parseBots( String filename ) throws IOException {
        final Map<String, Vector<String[]>> sectionMap = parseCommaSepratedFile( filename );
        final Vector<StarcraftBot> ret = new Vector<StarcraftBot>();
        final Vector<String[]> bots = sectionMap.get( BOT_SECTION );
        for (final String[] botString : bots) {
            if (botString.length != 3) {
                LOGGER.warning( filename + " contains invalid bot: " + Arrays.toString( botString ) );
            }
            else {
                try {
                    final String name = botString[0];
                    final String race = botString[1];
                    final Long hex = Long.decode( botString[2] );
                    final boolean bechmark = false;
                    final File f = new File( "..\\Bots\\" + name + "\\Bot\\" + name + ".dll" );
                    if (!f.exists() || !f.canRead()) {
                        LOGGER.warning( "Can't access ..\\Bots\\" + name + "\\Bot\\" + name + ".dll. Ignoring" );
                    }
                    else {
                        LOGGER.info( "Found ..\\Bots\\" + name + "\\Bot\\" + name + ".dll." );
                        ret.add( new StarcraftBot( name, hex, race, bechmark ) );
                    }
                }
                catch (final Exception e) {
                    LOGGER.warning( filename + " contains invalid bot: " + Arrays.toString( botString ) );
                }
            }
        }

        final Vector<String[]> botsBench = sectionMap.get( BOT_SECTION_BENCHMARK );
        for (final String[] botString : botsBench) {
            if (botString.length != 3) {
                LOGGER.warning( filename + " contains invalid bot: " + Arrays.toString( botString ) );
            }
            else {
                try {
                    final String name = botString[0];
                    final String race = botString[1];
                    final Long hex = Long.decode( botString[2] );
                    final boolean bechmark = true;

                    ret.add( new StarcraftBot( name, hex, race, bechmark ) );

                }
                catch (final Exception e) {
                    e.printStackTrace();
                    LOGGER.warning( filename + " contains invalid bot: " + Arrays.toString( botString ) );
                }
            }
        }
        LOGGER.info( "Parsed " + ret.size() + " bots" );
        return ret;
    }

    private static Map<String, Vector<String[]>> parseCommaSepratedFile( String filename ) throws IOException {
        BufferedReader reader = null;
        final Map<String, Vector<String[]>> ret = new HashMap<String, Vector<String[]>>();
        ret.put( null, new Vector<String[]>() );
        String currentSection = null;
        try {
            reader = new BufferedReader( new FileReader( new File( filename ) ) );
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.isEmpty()) {
                    continue;
                }
                if (line.startsWith( "#" )) {
                    continue;
                }

                if (line.startsWith( "[" )) {
                    //Just assume it ends with ']
                    currentSection = line.substring( 1, line.length() - 1 );
                    ret.put( currentSection, new Vector<String[]>() );
                }
                else {
                    final String[] tokens = line.split( "," );
                    for (int i = 0; i < tokens.length; i++) {
                        tokens[i] = tokens[i].trim();
                    }
                    ret.get( currentSection ).add( tokens );
                }
            }
        }
        catch (final IOException e) {
            throw e;
        }
        finally {
            if (reader != null) {
                reader.close();
            }
        }

        return ret;
    }

    public static Vector<StarcraftMap> parseMaps( String filename ) throws IOException {
        final Map<String, Vector<String[]>> sectionMap = parseCommaSepratedFile( filename );
        final Vector<StarcraftMap> ret = new Vector<StarcraftMap>();
        final Vector<String[]> mapStrings = sectionMap.get( null );
        for (final String[] mapString : mapStrings) {
            if (mapString.length < 2) {
                LOGGER.warning( filename + " contains invalid map: " + Arrays.toString( mapString ) );
            }
            else {
                final File f = new File( "..\\" + mapString[1] );
                if (!f.exists() || !f.canRead()) {
                    LOGGER.warning( "Can't access ..\\" + mapString[1] + ". Ignoring" );
                }
                else {
                    if (mapString.length < 3) {
                        LOGGER.warning( mapString[0] + " has no BWTA file. Bots using BWTA will generate it everytime the map is played" );
                        ret.add( new StarcraftMap( mapString[0], mapString[1] ) );
                    }
                    else {
                        final File bwta = new File( "..\\Maps\\" + mapString[2] + ".bwta" );
                        if (!bwta.exists() || !bwta.canRead()) {
                            LOGGER.warning( "Can't access..\\Maps\\" + mapString[2] + ".bwta. Ignoring" );
                        }
                        else {
                            ret.add( new StarcraftMap( mapString[0], mapString[1], mapString[2] ) );
                        }

                    }

                }
            }
        }
        LOGGER.info( "Parsed " + ret.size() + " maps" );
        return ret;
    }
}
